﻿using System;

namespace DefaultDspPluginsLib.Depricated
{
    public static class Effect_Compressor
    {
        public static void Process(ref DefaultDspPlugins.Effects.Compressor.CompressorData data, double[] wav_in_left, double[] wav_in_right, double[] wav_out_left, double[] wav_out_right)
        {
            int n = wav_in_left.Length;          // N samples
            double threshold = data.threshold;  // threshold (percents)
            double slope = data.slope;      // slope angle (percents)
            int sr = (int)data.sr;         // sample rate (smp/sec)
            double tla = data.tla;        // lookahead  (ms)
            double twnd = data.twnd;       // window time (ms)
            double tatt = data.tatt;       // attack time  (ms)
            double trel = data.trel;       // release time (ms)

            //typedef float stereodata[2];
            threshold *= 0.01;          // threshold to unity (0...1)
            slope *= 0.01;              // slope to unity
            tla *= 1e-3;                // lookahead time to seconds
            twnd *= 1e-3;               // window time to seconds
            tatt *= 1e-3;               // attack time to seconds
            trel *= 1e-3;               // release time to seconds

            // attack and release "per sample decay"
            double att = (tatt == 0.0) ? (0.0) : Math.Exp(-1.0 / (sr * tatt));
            double rel = (trel == 0.0) ? (0.0) : Math.Exp(-1.0 / (sr * trel));

            // sample offset to lookahead wnd start
            int lhsmp = (int)(sr * tla);

            // samples count in lookahead window
            int nrms = (int)(sr * twnd);

            double inputGain = data.inputGain;
            double outputGain = data.outputGain;

            // for each sample...
            for (int i = 0; i < n; ++i)
            {
                // now compute RMS
                double summ = 0;

                // for each sample in window
                for (int j = 0; j < nrms; ++j)
                {
                    int lki = i + j + lhsmp;
                    double smp;

                    // if we in bounds of signal?
                    // if so, convert to mono
                    if (lki < n)
                        smp = 0.5 * (wav_in_left[lki] * inputGain) + 0.5 * (wav_in_right[lki] * inputGain);
                    else
                        smp = 0.0;      // if we out of bounds we just get zero in smp

                    summ += smp * smp;  // square em..
                }

                double rms = Math.Sqrt(summ / nrms);   // root-mean-square

                // dynamic selection: attack or release?
                double theta = rms > data.env ? att : rel;

                // smoothing with capacitor, envelope extraction...
                // here be aware of pIV denormal numbers glitch
                data.env = (1.0 - theta) * rms + theta * data.env;

                // the very easy hard knee 1:N compressor
                double gain = 1.0;
                if (data.env > threshold)
                {
                    gain = gain - (data.env - threshold) * slope;
                }

                // result - two hard kneed compressed channels...
                wav_out_left[i] = wav_in_left[i] * inputGain * gain * outputGain;
                wav_out_right[i] = wav_in_right[i] * inputGain * gain * outputGain;
            }
        }
    }
}
